﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using SGD;

namespace CharacterTool
{
    public partial class MainForm : Form
    {
        public enum STATES
        {
            STATE_IDLE,
            STATE_MOVE,
            STATE_JUMP,
            STATE_ATTACK,
            STATE_MAX
        };

        // The current version of this file.
        public int m_nVersion = 2;

        // A flag to check if the form is running.
        public bool m_bRunning;

        // The currently selected body part
        int m_nCurrentSelected = 0;

        // The texture ID
        int m_nTextureID = -1;
        int m_nCrossID = -1;
        int m_nPixelID = -1;

        // Direct3D Manager instance
        ManagedDirect3D m_pDirect3D = ManagedDirect3D.Instance;
        
        // Texture Manager instance
        ManagedTextureManager m_pTextureManager = ManagedTextureManager.Instance;

        // The body part array
        CBodyPart[] m_BodyList = new CBodyPart[(int)BODY_PARTS.BODY_MAX];

        // The parents positions to simulate where to render the body parts off of.
        int m_nParentX = 0;
        int m_nParentY = 0;

        // Animation Variables
        bool m_bAnimating = false;

        // Resource directory
        string m_Resources = "../../Resources/";

        public MainForm()
        {
            InitializeComponent();

            // Initialize Direct3D
            if (!m_pDirect3D.InitManagedDirect3D(RenderPanel, true))
            {
                MessageBox.Show("Direct3D failed to initialize!", "Error!");
                Close();
                return;
            }

            // Initialize TextureManager
            if (!m_pTextureManager.InitManagedTextureManager(m_pDirect3D.Device, m_pDirect3D.Sprite))
            {
                MessageBox.Show("TextureManager failed to initialize!", "Error!");
                Close();
                return;
            }

            BodyPartSelect(m_nCurrentSelected);
            m_nParentX = RenderPanel.Size.Width >> 1;
            m_nParentY = RenderPanel.Size.Height >> 1;

            // Load in a texture of... myself! :D
            m_nTextureID = m_pTextureManager.LoadTexture(m_Resources + "Michael.png", 0);
            m_nCrossID = m_pTextureManager.LoadTexture(m_Resources + "Cross.png", 0);
            m_nPixelID = m_pTextureManager.LoadTexture(m_Resources + "Pixel.png", 0);

            RECT_LEFT.Maximum = m_pTextureManager.GetTextureWidth(m_nTextureID);
            RECT_TOP.Maximum = m_pTextureManager.GetTextureHeight(m_nTextureID);
            RECT_WIDTH.Maximum = m_pTextureManager.GetTextureWidth(m_nTextureID);
            RECT_HEIGHT.Maximum = m_pTextureManager.GetTextureHeight(m_nTextureID);

            for (int i = 0; i < (int)BODY_PARTS.BODY_MAX; ++i)
            {
                m_BodyList[i] = new CBodyPart(m_nParentX, m_nParentY, (BODY_PARTS)i);
                m_BodyList[i].Update();
            }

            // The default file that will be loaded at startup.
            LoadFile(m_Resources + "Default_ver2.TLOWC");

            // Default index.
            CurrentStateBox.SelectedIndex = (int)STATES.STATE_IDLE;

            button2.Enabled = false;

            // The form initialized successfully.
            m_bRunning = true;
        }

        public void Process()
        {
            foreach (CBodyPart limb in m_BodyList)
            {
                limb.Update();
                if (m_bAnimating)
                    limb.Animate(CurrentStateBox.SelectedIndex);
            }

            m_BodyList[m_nCurrentSelected].m_Rect.X = (int)RECT_LEFT.Value;
            m_BodyList[m_nCurrentSelected].m_Rect.Y = (int)RECT_TOP.Value;
            m_BodyList[m_nCurrentSelected].m_Rect.Width = (int)RECT_WIDTH.Value;
            m_BodyList[m_nCurrentSelected].m_Rect.Height = (int)RECT_HEIGHT.Value;

            if (m_bAnimating)
            {
                Head_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_fAngle;
                Torso_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_fAngle;
                LeftArm_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_fAngle;
                RightArm_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_fAngle;
                LeftLeg_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_fAngle;
                RightLeg_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_fAngle;
            }
            else
            {
                m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_fAngle = (float)Head_Angle.Value;
                m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_fAngle = (float)Torso_Angle.Value;
                m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_fAngle = (float)LeftArm_Angle.Value;
                m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_fAngle = (float)RightArm_Angle.Value;
                m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_fAngle = (float)LeftLeg_Angle.Value;
                m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_fAngle = (float)RightLeg_Angle.Value;
            }

            m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nJointX = (int)Head_JointX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nJointY = (int)Head_JointY.Value;
            m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nOriginX = (int)Head_OriginX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nOriginY = (int)Head_OriginY.Value;

            m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nJointX = (int)Torso_JointX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nJointY = (int)Torso_JointY.Value;
            m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nOriginX = (int)Torso_OriginX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nOriginY = (int)Torso_OriginY.Value;

            m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nJointX = (int)LeftArm_JointX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nJointY = (int)LeftArm_JointY.Value;
            m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nOriginX = (int)LeftArm_OriginX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nOriginY = (int)LeftArm_OriginY.Value;

            m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nJointX = (int)RightArm_JointX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nJointY = (int)RightArm_JointY.Value;
            m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nOriginX = (int)RightArm_OriginX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nOriginY = (int)RightArm_OriginY.Value;

            m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nJointX = (int)LeftLeg_JointX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nJointY = (int)LeftLeg_JointY.Value;
            m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nOriginX = (int)LeftLeg_OriginX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nOriginY = (int)LeftLeg_OriginY.Value;

            m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nJointX = (int)RightLeg_JointX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nJointY = (int)RightLeg_JointY.Value;
            m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nOriginX = (int)RightLeg_OriginX.Value;
            m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nOriginY = (int)RightLeg_OriginY.Value;
        }

        public void Render()
        {
            // Begin rendering.
            m_pDirect3D.ChangeDisplayParam(RenderPanel, true);
            m_pDirect3D.Clear(0, 162, 232);
            m_pDirect3D.DeviceBegin();
            m_pDirect3D.SpriteBegin();
            m_pDirect3D.LineBegin();

            // Render the origin lines.
            m_pDirect3D.DrawLine(RenderPanel.Size.Width / 2, 0, RenderPanel.Size.Width / 2, RenderPanel.Size.Height, 255, 0, 0);
            m_pDirect3D.DrawLine(0, RenderPanel.Size.Height / 2, RenderPanel.Size.Width, RenderPanel.Size.Height / 2, 0, 0, 255);

            RenderBody();

            // Render the Min/Max Lines
            if (MINMAX_Checkbox.Checked)
            {
                for (int i = 0; i < 25; ++i)
                {
                    float x = m_BodyList[m_nCurrentSelected].m_nJointX + m_BodyList[m_nCurrentSelected].m_nOriginX;
                    float y = m_BodyList[m_nCurrentSelected].m_nJointY + m_BodyList[m_nCurrentSelected].m_nOriginY;
                    
                    float dx = 0;
                    float dy = 0;

                    if (HORT_Checkbox.Checked)
                        dx = x + i * (float)Math.Sin((double)Min.Value);
                    else
                        dx = x - i * (float)Math.Sin((double)Min.Value);

                    if (VERT_Checkbox.Checked)
                        dy = y + i * (float)Math.Cos((double)Min.Value);
                    else
                        dy = y - i * (float)Math.Cos((double)Min.Value);

                    m_pTextureManager.Draw(m_nPixelID, (int)dx, (int)dy, 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(0, 255, 0).ToArgb());

                    if (HORT_Checkbox.Checked)
                        dx = x + i * (float)Math.Sin((double)Max.Value);
                    else
                        dx = x - i * (float)Math.Sin((double)Max.Value);

                    if (VERT_Checkbox.Checked)
                        dy = y + i * (float)Math.Cos((double)Max.Value);
                    else
                        dy = y - i * (float)Math.Cos((double)Max.Value);

                    m_pTextureManager.Draw(m_nPixelID, (int)dx, (int)dy, 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(255, 0, 255).ToArgb());
                }
            }

            // End rendering.
            m_pDirect3D.LineEnd();
            m_pDirect3D.SpriteEnd();
            m_pDirect3D.DeviceEnd();
            m_pDirect3D.Present();

            RenderTexturePanel();
        }

        void RenderTexturePanel()
        {
            // Begin rendering.
            m_pDirect3D.ChangeDisplayParam(TexturePanel, true);
            m_pDirect3D.Clear(0, 162, 232);
            m_pDirect3D.DeviceBegin();
            m_pDirect3D.SpriteBegin();
            m_pDirect3D.LineBegin();

            // ONLY if the RECT checkbox if checked.
            if (RECT_checkBox.Checked)
            {
                Rectangle offsetRect = m_BodyList[m_nCurrentSelected].m_Rect;
                m_pDirect3D.DrawRect(offsetRect, 0, 255, 0);
            }

            Rectangle rect = new Rectangle(0, 0, 0, 0);

            m_pTextureManager.Draw(m_nTextureID, 0, 0, 1.0f, 1.0f, rect, 0, 0, 0.0f, 0);

            // End rendering.
            m_pDirect3D.LineEnd();
            m_pDirect3D.SpriteEnd();
            m_pDirect3D.DeviceEnd();
            m_pDirect3D.Present();
        }

        void RenderBody()
        {
            int x = m_BodyList[m_nCurrentSelected].m_nJointX;
            int y = m_BodyList[m_nCurrentSelected].m_nJointY;
            int originx = m_BodyList[m_nCurrentSelected].m_nOriginX;
            int originy = m_BodyList[m_nCurrentSelected].m_nOriginY;

            // Render the body in the correct layer order.
            RenderLimb((int)BODY_PARTS.BODY_LEG_LEFT);
            RenderLimb((int)BODY_PARTS.BODY_ARM_LEFT);
            RenderLimb((int)BODY_PARTS.BODY_TORSO);
            RenderLimb((int)BODY_PARTS.BODY_LEG_RIGHT);
            RenderLimb((int)BODY_PARTS.BODY_HEAD);
            RenderLimb((int)BODY_PARTS.BODY_ARM_RIGHT);

            if (ORIGIN_CHECK.Checked)
            {
                for (int i = 0; i < 5; ++i)
                {
                    m_pTextureManager.Draw(m_nPixelID, (x + originx) + i, (y + originy), 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(255, 0, 0).ToArgb());
                    m_pTextureManager.Draw(m_nPixelID, (x + originx) - i, (y + originy), 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(255, 0, 0).ToArgb());

                    m_pTextureManager.Draw(m_nPixelID, (x + originx), (y + originy) + i, 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(255, 0, 0).ToArgb());
                    m_pTextureManager.Draw(m_nPixelID, (x + originx), (y + originy) - i, 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(255, 0, 0).ToArgb());
                }
                m_pTextureManager.Draw(m_nPixelID, (x + originx), (y + originy), 1.0f, 1.0f, Rectangle.Empty, 0, 0, 0.0f, Color.FromArgb(0, 0, 255).ToArgb());
            }
        }

        void RenderLimb(int nIndex)
        {
            if (nIndex == (int)BODY_PARTS.BODY_MAX)
                return;

            if (HIDE_Checkbox.Checked)
                if (nIndex != m_nCurrentSelected)
                    return;

            m_pTextureManager.Draw(m_nTextureID, m_BodyList[nIndex].m_nJointX, m_BodyList[nIndex].m_nJointY, 1.0f, 1.0f, m_BodyList[nIndex].m_Rect, m_BodyList[nIndex].m_nOriginX, m_BodyList[nIndex].m_nOriginY, m_BodyList[nIndex].m_fAngle, 0);
        }

        void BodyPartSelect(int nIndex)
        {
            m_nCurrentSelected = nIndex;

            if (m_BodyList[m_nCurrentSelected] != null)
            {
                RECT_LEFT.Value = m_BodyList[m_nCurrentSelected].m_Rect.Left;
                RECT_TOP.Value = m_BodyList[m_nCurrentSelected].m_Rect.Top;
                RECT_WIDTH.Value = m_BodyList[m_nCurrentSelected].m_Rect.Width;
                RECT_HEIGHT.Value = m_BodyList[m_nCurrentSelected].m_Rect.Height;

                Min.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMin;
                Max.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMax;
                AnimateSpeed.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fSpeed;

                INVERT_Checkbox.Checked = m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_bInitialDir;
            }

            // Disable all editor forms for the Body Part Control and only enable the index passed in.
            Head_Angle.Enabled = false;
            Head_JointX.Enabled = false;
            Head_JointY.Enabled = false;
            Head_OriginX.Enabled = false;
            Head_OriginY.Enabled = false;

            Torso_Angle.Enabled = false;
            Torso_JointX.Enabled = false;
            Torso_JointY.Enabled = false;
            Torso_OriginX.Enabled = false;
            Torso_OriginY.Enabled = false;

            LeftArm_Angle.Enabled = false;
            LeftArm_JointX.Enabled = false;
            LeftArm_JointY.Enabled = false;
            LeftArm_OriginX.Enabled = false;
            LeftArm_OriginY.Enabled = false;

            RightArm_Angle.Enabled = false;
            RightArm_JointX.Enabled = false;
            RightArm_JointY.Enabled = false;
            RightArm_OriginX.Enabled = false;
            RightArm_OriginY.Enabled = false;

            LeftLeg_Angle.Enabled = false;
            LeftLeg_JointX.Enabled = false;
            LeftLeg_JointY.Enabled = false;
            LeftLeg_OriginX.Enabled = false;
            LeftLeg_OriginY.Enabled = false;

            RightLeg_Angle.Enabled = false;
            RightLeg_JointX.Enabled = false;
            RightLeg_JointY.Enabled = false;
            RightLeg_OriginX.Enabled = false;
            RightLeg_OriginY.Enabled = false;

            switch (nIndex)
            {
                case 0:
                    {
                        Head_Angle.Enabled = true;
                        Head_JointX.Enabled = true;
                        Head_JointY.Enabled = true;
                        Head_OriginX.Enabled = true;
                        Head_OriginY.Enabled = true;
                    }
                    break;
                case 1:
                    {
                        Torso_Angle.Enabled = true;
                        Torso_JointX.Enabled = true;
                        Torso_JointY.Enabled = true;
                        Torso_OriginX.Enabled = true;
                        Torso_OriginY.Enabled = true;
                    }
                    break;
                case 2:
                    {
                        LeftArm_Angle.Enabled = true;
                        LeftArm_JointX.Enabled = true;
                        LeftArm_JointY.Enabled = true;
                        LeftArm_OriginX.Enabled = true;
                        LeftArm_OriginY.Enabled = true;
                    }
                    break;
                case 3:
                    {
                        RightArm_Angle.Enabled = true;
                        RightArm_JointX.Enabled = true;
                        RightArm_JointY.Enabled = true;
                        RightArm_OriginX.Enabled = true;
                        RightArm_OriginY.Enabled = true;
                    }
                    break;
                case 4:
                    {
                        LeftLeg_Angle.Enabled = true;
                        LeftLeg_JointX.Enabled = true;
                        LeftLeg_JointY.Enabled = true;
                        LeftLeg_OriginX.Enabled = true;
                        LeftLeg_OriginY.Enabled = true;
                    }
                    break;
                case 5:
                    {
                        RightLeg_Angle.Enabled = true;
                        RightLeg_JointX.Enabled = true;
                        RightLeg_JointY.Enabled = true;
                        RightLeg_OriginX.Enabled = true;
                        RightLeg_OriginY.Enabled = true;
                    }
                    break;
                default:
                    break;
            }
        }

        void UpdateFormWithData()
        {
            RECT_LEFT.Value = m_BodyList[m_nCurrentSelected].m_Rect.X;
            RECT_TOP.Value = m_BodyList[m_nCurrentSelected].m_Rect.Y;
            RECT_WIDTH.Value = m_BodyList[m_nCurrentSelected].m_Rect.Width;
            RECT_HEIGHT.Value = m_BodyList[m_nCurrentSelected].m_Rect.Height;

            if (CurrentStateBox.SelectedIndex != -1)
            {
                Min.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMin;
                Max.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMax;
                AnimateSpeed.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fSpeed;
            }

            Head_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_fAngle;
            Head_JointX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nJointX;
            Head_JointY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nJointY;
            Head_OriginX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nOriginX;
            Head_OriginY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_HEAD].m_nOriginY;

            Torso_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_fAngle;
            Torso_JointX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nJointX;
            Torso_JointY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nJointY;
            Torso_OriginX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nOriginX;
            Torso_OriginY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_TORSO].m_nOriginY;

            LeftArm_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_fAngle;
            LeftArm_JointX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nJointX;
            LeftArm_JointY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nJointY;
            LeftArm_OriginX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nOriginX;
            LeftArm_OriginY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_LEFT].m_nOriginY;

            RightArm_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_fAngle;
            RightArm_JointX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nJointX;
            RightArm_JointY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nJointY;
            RightArm_OriginX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nOriginX;
            RightArm_OriginY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_ARM_RIGHT].m_nOriginY;

            LeftLeg_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_fAngle;
            LeftLeg_JointX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nJointX;
            LeftLeg_JointY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nJointY;
            LeftLeg_OriginX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nOriginX;
            LeftLeg_OriginY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_LEFT].m_nOriginY;

            RightLeg_Angle.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_fAngle;
            RightLeg_JointX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nJointX;
            RightLeg_JointY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nJointY;
            RightLeg_OriginX.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nOriginX;
            RightLeg_OriginY.Value = (decimal)m_BodyList[(int)BODY_PARTS.BODY_LEG_RIGHT].m_nOriginY;
        }

        void SaveFile()
        {
            SaveFileDialog DLG = new SaveFileDialog();
            DLG.Filter = "TLOW Character Files(*.TLOWC)|*.TLOWC";

            if (DialogResult.OK == DLG.ShowDialog())
            {
                FileInfo f = new FileInfo(DLG.FileName);
                BinaryWriter Writer = new BinaryWriter(f.OpenWrite());

                // Begin file
                Writer.Write(m_nVersion);

                foreach (CBodyPart bodyPart in m_BodyList)
                {
                    Writer.Write((int)bodyPart.m_nBodyTypeID);
                    Writer.Write(bodyPart.m_nOriginX);
                    Writer.Write(bodyPart.m_nOriginY);
                    Writer.Write(bodyPart.m_nJointX);
                    Writer.Write(bodyPart.m_nJointY);
                    Writer.Write(bodyPart.m_Rect.X);
                    Writer.Write(bodyPart.m_Rect.Y);
                    Writer.Write(bodyPart.m_Rect.Right);
                    Writer.Write(bodyPart.m_Rect.Bottom);
                    Writer.Write(bodyPart.m_fAngle);

                    foreach (CAnimation animation in bodyPart.m_AnimationBank)
                    {
                        Writer.Write(animation.m_fMin);
                        Writer.Write(animation.m_fMax);
                        Writer.Write(animation.m_fSpeed);
                        Writer.Write(animation.m_bInitialDir);
                    }
                }

                // End file
                Writer.Close();
            }
        }

        void OpenFile()
        {
            OpenFileDialog DLG = new OpenFileDialog();
            DLG.Filter = "TLOW Character Files(*.TLOWC)|*.TLOWC";

            if (DialogResult.OK == DLG.ShowDialog())
            {
                LoadFile(DLG.FileName);
            }
        }

        void LoadFile(string file)
        {
            FileInfo f = new FileInfo(file);
            BinaryReader Reader = new BinaryReader(f.OpenRead());

            int nVersion = Reader.ReadInt32();

            foreach (CBodyPart bodyPart in m_BodyList)
            {
                bodyPart.m_nBodyTypeID = (BODY_PARTS)Reader.ReadInt32();
                bodyPart.m_nOriginX = Reader.ReadInt32();
                bodyPart.m_nOriginY = Reader.ReadInt32();
                bodyPart.m_nJointX = Reader.ReadInt32();
                bodyPart.m_nJointY = Reader.ReadInt32();
                bodyPart.m_Rect.X = Reader.ReadInt32();
                bodyPart.m_Rect.Y = Reader.ReadInt32();
                bodyPart.m_Rect.Width = Reader.ReadInt32();
                bodyPart.m_Rect.Height = Reader.ReadInt32();
                bodyPart.m_fAngle = Reader.ReadSingle();

                bodyPart.m_Rect.Width -= bodyPart.m_Rect.X;
                bodyPart.m_Rect.Height -= bodyPart.m_Rect.Y;

                if (nVersion >= 2)
                {
                    foreach (CAnimation animation in bodyPart.m_AnimationBank)
                    {
                        animation.m_fMin = Reader.ReadSingle();
                        animation.m_fMax = Reader.ReadSingle();
                        animation.m_fSpeed = Reader.ReadSingle();
                        animation.m_bInitialDir = Reader.ReadBoolean();
                    }
                }
            }

            Reader.Close();
            UpdateFormWithData();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            m_bRunning = false;
            m_pTextureManager.ShutdownManagedTextureManager();
        }

        private void Head_Select_Click(object sender, EventArgs e)
        {
            if (m_nCurrentSelected != 0)
            {
                m_nCurrentSelected = 0;
                BodyPartSelect(m_nCurrentSelected);
            }
        }

        private void Torso_Select_Click(object sender, EventArgs e)
        {
            if (m_nCurrentSelected != 1)
            {
                m_nCurrentSelected = 1;
                BodyPartSelect(m_nCurrentSelected);
            }
        }

        private void LeftArm_Select_Click(object sender, EventArgs e)
        {
            if (m_nCurrentSelected != 2)
            {
                m_nCurrentSelected = 2;
                BodyPartSelect(m_nCurrentSelected);
            }
        }

        private void RightArm_Select_Click(object sender, EventArgs e)
        {
            if (m_nCurrentSelected != 3)
            {
                m_nCurrentSelected = 3;
                BodyPartSelect(m_nCurrentSelected);
            }
        }

        private void LeftLeg_Select_Click(object sender, EventArgs e)
        {
            if (m_nCurrentSelected != 4)
            {
                m_nCurrentSelected = 4;
                BodyPartSelect(m_nCurrentSelected);
            }
        }

        private void RightLeg_Select_Click(object sender, EventArgs e)
        {
            if (m_nCurrentSelected != 5)
            {
                m_nCurrentSelected = 5;
                BodyPartSelect(m_nCurrentSelected);
            }
        }

        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            SaveFile();
        }

        private void openToolStripButton_Click(object sender, EventArgs e)
        {
            OpenFile();
        }

        private void loadTextureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog DLG = new OpenFileDialog();
            DLG.Filter = "Image Files(*.BMP;*.JPG;*.GIF;*.PNG)|*.BMP;*.JPG;*.GIF;*.PNG";

            if (DialogResult.OK == DLG.ShowDialog())
            {
                m_pTextureManager.ReleaseTexture(m_nTextureID);
                m_nTextureID = m_pTextureManager.LoadTexture(DLG.FileName, 0);

                RECT_LEFT.Maximum = m_pTextureManager.GetTextureWidth(m_nTextureID);
                RECT_TOP.Maximum = m_pTextureManager.GetTextureHeight(m_nTextureID);
                RECT_WIDTH.Maximum = m_pTextureManager.GetTextureWidth(m_nTextureID);
                RECT_HEIGHT.Maximum = m_pTextureManager.GetTextureHeight(m_nTextureID);

            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFile();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFile();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (m_bAnimating == false)
            {
                button2.Enabled = true;
                button1.Enabled = false;

                m_bAnimating = true;
                m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_bAnimateDir = m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_bInitialDir;
                toolStripStatusLabel1.Text = "Animation Status : PLAYING";
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (m_bAnimating == true)
            {
                button2.Enabled = false;
                button1.Enabled = true;

                m_bAnimating = false;
                toolStripStatusLabel1.Text = "Animation Status : PAUSED";
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < (int)BODY_PARTS.BODY_MAX; ++i)
            {
                m_BodyList[i].m_fAngle = 0.0f;
            }
            UpdateFormWithData();
        }

        private void CurrentStateBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            Min.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMin;
            Max.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMax;
            AnimateSpeed.Value = (decimal)m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fSpeed;

            for (int i = 0; i < (int)BODY_PARTS.BODY_MAX; ++i)
            {
                m_BodyList[i].m_fAngle = 0.0f;
            }
            UpdateFormWithData();

            if (m_bAnimating == true)
            {
                m_bAnimating = false;
                toolStripStatusLabel1.Text = "Animation Status : PAUSED";
            }
        }

        private void Min_ValueChanged(object sender, EventArgs e)
        {
            m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMin = (float)Min.Value;
        }

        private void Max_ValueChanged(object sender, EventArgs e)
        {
            m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fMax = (float)Max.Value;
        }

        private void AnimateSpeed_ValueChanged(object sender, EventArgs e)
        {
            m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_fSpeed = (float)AnimateSpeed.Value;
        }

        private void INVERT_Checkbox_CheckedChanged(object sender, EventArgs e)
        {
            m_BodyList[m_nCurrentSelected].m_AnimationBank[CurrentStateBox.SelectedIndex].m_bInitialDir = INVERT_Checkbox.Checked;
        }
    }
}
